package com.hospital.hospitalsystem.modules.user.biz;

import com.github.pagehelper.PageHelper;
import com.hospital.hospitalsystem.base.PageData;
import com.hospital.hospitalsystem.modules.hospital.dao.entity.DepartmentEntity;
import com.hospital.hospitalsystem.modules.hospital.dao.entity.DoctorOrderDetailEntity;
import com.hospital.hospitalsystem.modules.hospital.dto.DepartmentRsp;
import com.hospital.hospitalsystem.modules.hospital.service.DepartmentService;
import com.hospital.hospitalsystem.modules.hospital.service.DoctorOrderDetailService;
import com.hospital.hospitalsystem.modules.login.dao.entity.DoctorEntity;
import com.hospital.hospitalsystem.modules.login.dao.entity.HospitalMessageEntity;
import com.hospital.hospitalsystem.modules.login.dao.entity.UserMessageEntity;
import com.hospital.hospitalsystem.modules.login.dto.EmailEntityExt;
import com.hospital.hospitalsystem.modules.login.service.DoctorService;
import com.hospital.hospitalsystem.modules.login.service.HospitalMessageService;
import com.hospital.hospitalsystem.modules.login.service.UserMessageService;
import com.hospital.hospitalsystem.modules.medicine.dao.entity.HospitalMedicalEntity;
import com.hospital.hospitalsystem.modules.medicine.dto.HospitalMedicalRsp;
import com.hospital.hospitalsystem.modules.medicine.service.HospitalMedicalService;
import com.hospital.hospitalsystem.modules.user.dao.entity.BookEntity;
import com.hospital.hospitalsystem.modules.user.dao.entity.OrderEntity;
import com.hospital.hospitalsystem.modules.user.dto.*;
import com.hospital.hospitalsystem.modules.user.service.BookService;
import com.hospital.hospitalsystem.modules.user.service.OrderService;
import com.hospital.hospitalsystem.utils.SendEmailUtils;
import javafx.util.Pair;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.jboss.logging.Cause;
import org.simpleframework.xml.Order;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author qiancheng@cqxyy.net
 * @date 2023/2/23
 */
@Service
public class UserBiz {

    @Autowired
    private UserMessageService userMessageService;

    @Autowired
    private BookService bookService;

    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private DoctorService doctorService;

    @Autowired
    private HospitalMessageService hospitalMessageService;

    @Autowired
    private DoctorOrderDetailService doctorOrderDetailService;

    @Autowired
    private HospitalMedicalService hospitalMedicalService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private SendEmailUtils sendEmailUtils;

    /**
     * 获取医院列表
     * @param req
     * @return
     */
    public PageData<HospitalListRsp> hospitalList(HospitalListReq req) {
        Example example = new Example(HospitalMessageEntity.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(req.getHospitalName())){
            criteria.andLike("name","%" + req.getHospitalName() + "%");
        }
        if (req.getStatus() != null){
            criteria.andEqualTo("status",req.getStatus());
        }
        com.github.pagehelper.Page<HospitalListRsp> page = PageHelper.startPage(
                req.getCurrentPage(), req.getPageSize()
        );
        List<HospitalListRsp> result = hospitalMessageService.selectByExample(example).stream().map(s ->{
            HospitalListRsp hospitalListRsp = new HospitalListRsp();
            hospitalListRsp.setHospitalUuid(s.getUuid());
            hospitalListRsp.setHospitalName(s.getName());
            String html = StringEscapeUtils.escapeHtml(s.getIntroduceHtml());
            hospitalListRsp.setIntroduceHtml(html);
            hospitalListRsp.setAddress(s.getAddress());
            return hospitalListRsp;
        }).collect(Collectors.toList());
        int longs = ((Number) page.getTotal()).intValue();
        PageData<HospitalListRsp> pageData = PageData.of(result,page.getPageNum(),page.getPageSize(),longs);
        return pageData;
    }

    /**
     * 查看医生预约信息情况
     * @param req
     * @return
     */
    public BookCaseRsp doctorBookCase(BookCaseReq req) {
        req.setNowDate(new Date());
        List<BookTimeResultExt> tmp = doctorService.selectBookTimeByUuid(req);
        if(CollectionUtils.isEmpty(tmp)){
            throw new RuntimeException("该医生没有排班");
        }
        BookCaseRsp bookCaseRsp = new BookCaseRsp();
        BeanUtils.copyProperties(tmp.get(0),bookCaseRsp);
        Map<String,List<BookTimeExt>> bookTimes = tmp.stream().map(s ->{
            BookTimeExt bookTime = new BookTimeExt();
            BeanUtils.copyProperties(s,bookTime);
            Date date = s.getDate();
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            bookTime.setDate(dateFormat.format(date));
            return bookTime;
        }).collect(Collectors.groupingBy(BookTimeExt::getDate));
        List<BookTimeExts> days = new ArrayList<>();
        bookTimes.forEach((key,value) ->{
            BookTimeExts bookTimeExts = new BookTimeExts();
            bookTimeExts.setDate(key);
            List<BookTimeExt> times = new ArrayList<>();
            value.forEach(s ->{
                times.add(s);
            });
            bookTimeExts.setTimes(times);
            days.add(bookTimeExts);
        });
        bookCaseRsp.setBook(days);
        Example example = new Example(DepartmentEntity.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("code",bookCaseRsp.getDepartment());
        List<DepartmentEntity> departmentEntities = departmentService.selectByExample(example);
        bookCaseRsp.setDepartment(departmentEntities.get(0).getName());
        return bookCaseRsp;
    }

    /**
     * 用户预约
     * @param req
     */
    @Transactional
    public void doctorOrder(OrderReq req) {
        Example exampleBook = new Example(BookEntity.class);
        Example.Criteria criteriaBook = exampleBook.createCriteria();
        criteriaBook.andEqualTo("userUuid",req.getUserUuid()).andIn("status", Arrays.asList(new String[]{"1","3"}));
        List<BookEntity> list = bookService.selectByExample(exampleBook);
        for (BookEntity bookEntity : list){
            if (bookEntity.getHospitalUuid().equals(req.getHospitalUuid()) && bookEntity.getDoctorUuid().equals(req.getDoctorUuid())
            && bookEntity.getDetailUuid().equals(req.getDetailUuid())){
                throw new RuntimeException("你已预约");
            }
        }
        Example exampleDetail = new Example(DoctorOrderDetailEntity.class);
        Example.Criteria criteriaDetail = exampleDetail.createCriteria();
        criteriaDetail.andEqualTo("hospitalUuid",req.getHospitalUuid()).andEqualTo("doctorUuid",req.getDoctorUuid())
                .andEqualTo("detailUuid",req.getDetailUuid());
        //当前预约的时间
        DoctorOrderDetailEntity doctorOrderDetailEntity = doctorOrderDetailService.selectOneByExample(exampleDetail);

        if (CollectionUtils.isNotEmpty(list)){
            List<OrderDetailExt> detailList = list.stream().map(s ->{
                OrderDetailExt orderDetailExt = new OrderDetailExt();
                BeanUtils.copyProperties(s,orderDetailExt);
                return orderDetailExt;
            }).collect(Collectors.toList());
            List<DoctorOrderDetailEntity> doctorOrderDetailEntities = doctorOrderDetailService.selectDetail(detailList);
            if (CollectionUtils.isNotEmpty(doctorOrderDetailEntities)){
                SimpleDateFormat dfDate = new SimpleDateFormat("yyyy-MM-dd");
                String date = dfDate.format(doctorOrderDetailEntity.getDate());
                for (DoctorOrderDetailEntity tmpEntity : doctorOrderDetailEntities){
                    if (date.equals(dfDate.format(tmpEntity.getDate()))){
                        if(doctorOrderDetailEntity.getStartTime().after(tmpEntity.getStartTime()) &&
                        doctorOrderDetailEntity.getEndTime().before(tmpEntity.getEndTime())){
                            throw new RuntimeException("你在这个时间段已有其他预约");
                        }
                    }
                }
            }
        }
        //向预约表中添加数据
        BookEntity bookEntity = new BookEntity();
        BeanUtils.copyProperties(req,bookEntity);
        bookEntity.setStatus(1);
        Integer surplus = doctorOrderDetailEntity.getSurplus();
        if (surplus <= 0){
            throw new RuntimeException("此医生没有预约空间");
        }
        doctorOrderDetailEntity.setSurplus(surplus - 1);
        doctorOrderDetailService.updateByPrimaryKeySelective(doctorOrderDetailEntity);
        bookEntity.setRank(doctorOrderDetailEntity.getTotal() - surplus + 1);
        bookEntity.setUuid(UUID.randomUUID().toString());
        bookService.insertSelective(bookEntity);
    }

    /**
     * 用户取消预约
     * @param req
     */
    @Transactional
    public void doctorOrderDelete(OrderReq req) {
        Example exampleBook = new Example(BookEntity.class);
        Example.Criteria criteriaBook = exampleBook.createCriteria();
        criteriaBook.andEqualTo("uuid",req.getOrderUuid());
        criteriaBook.andEqualTo("hospitalUuid",req.getHospitalUuid());
        criteriaBook.andEqualTo("doctorUuid",req.getDoctorUuid());
        criteriaBook.andEqualTo("detailUuid",req.getDetailUuid());
        BookEntity nowBookEntity = bookService.selectByExample(exampleBook).get(0);
        bookService.deleteByExample(exampleBook);
        Example exampleDetail = new Example(DoctorOrderDetailEntity.class);
        Example.Criteria criteriaDetail = exampleDetail.createCriteria();
        criteriaDetail.andEqualTo("hospitalUuid",req.getHospitalUuid()).andEqualTo("doctorUuid",req.getDoctorUuid())
                .andEqualTo("detailUuid",req.getDetailUuid());
        DoctorOrderDetailEntity doctorOrderDetailEntity = doctorOrderDetailService.selectOneByExample(exampleDetail);
        OrderDetailExt orderDetailExt = new OrderDetailExt();

        BookTimeResultExt bookTimeResultExt = new BookTimeResultExt();
        BeanUtils.copyProperties(doctorOrderDetailEntity,orderDetailExt);
        BeanUtils.copyProperties(doctorOrderDetailEntity,bookTimeResultExt);
        Example exampleDoctor = new Example(DoctorEntity.class);
        Example.Criteria criteriaDoctor = exampleDoctor.createCriteria();
        criteriaDoctor.andEqualTo("uuid",doctorOrderDetailEntity.getDoctorUuid());
        criteriaDoctor.andEqualTo("hospitalUuid",doctorOrderDetailEntity.getHospitalUuid());
        DoctorEntity doctorEntity = doctorService.selectOneByExample(exampleDoctor);
        bookTimeResultExt.setName(doctorEntity.getName());
        Map<OrderDetailExt,BookTimeResultExt> detailToTimeMap = new HashMap<>();

        detailToTimeMap.put(orderDetailExt,bookTimeResultExt);
        doctorOrderDetailEntity.setSurplus(doctorOrderDetailEntity.getSurplus() + 1);
        doctorOrderDetailService.updateByPrimaryKeySelective(doctorOrderDetailEntity);
        exampleBook = new Example(BookEntity.class);
        criteriaBook = exampleBook.createCriteria();
        criteriaBook.andEqualTo("hospitalUuid",req.getHospitalUuid());
        criteriaBook.andEqualTo("doctorUuid",req.getDoctorUuid());
        criteriaBook.andEqualTo("detailUuid",req.getDetailUuid());
        criteriaBook.andGreaterThan("rank",nowBookEntity.getRank());
        List<BookEntity> bookEntities = bookService.selectByExample(exampleBook);

        List<String> users = bookEntities.stream().map(BookEntity::getUserUuid).collect(Collectors.toList());;
        Map<String,BookEntity> bookEntityMap = bookEntities.stream().collect(Collectors.toMap(BookEntity::getUserUuid,s->s));
        Map<String,String> userAndEmails = null;
        if (CollectionUtils.isNotEmpty(users)){
            Example exampleUser = new Example(UserMessageEntity.class);
            Example.Criteria criteriaUser = exampleUser.createCriteria();
            criteriaUser.andIn("uuid",users);
            userAndEmails = userMessageService.selectByExample(exampleUser).stream()
                    .collect(Collectors.toMap(UserMessageEntity::getUuid,UserMessageEntity::getEmail));
        }

        if (req.getIsLevelChange() == 1) {
            //给排号变更的用户发送邮件
            if (CollectionUtils.isNotEmpty(bookEntities) && CollectionUtils.isNotEmpty(users)){
                for (BookEntity bookEntity : bookEntities){
                    bookEntity.setRank(bookEntity.getRank() - 1);
                    bookService.updateByPrimaryKeySelective(bookEntity);
                    String email = userAndEmails.get(bookEntity.getUserUuid());
                    EmailEntityExt emailEntityExt = new EmailEntityExt();
                    emailEntityExt.setEmail(email);
                    OrderDetailExt orderDetailExtIn = new OrderDetailExt();
                    BeanUtils.copyProperties(bookEntity,orderDetailExtIn);
                    BookTimeResultExt bookTimeResultExtIn = detailToTimeMap.get(orderDetailExtIn);
                    SimpleDateFormat dfDate = new SimpleDateFormat("yyyy-MM-dd");
                    SimpleDateFormat dfTime = new SimpleDateFormat("HH:mm:ss");
                    String data = "尊敬的用户,您在" + dfDate.format(bookTimeResultExtIn.getDate()) + " " +
                            dfTime.format(bookTimeResultExtIn.getStartTime()) + "——" + dfTime.format(bookTimeResultExtIn.getEndTime()) +
                            "预约的" + bookTimeResultExtIn.getName() + "医生的挂号由于在您前面预约的用户取消,所以你的排号变更为:" + (bookEntity.getRank());
                    emailEntityExt.setData(data);
                    sendEmailUtils.sendEmails(emailEntityExt);
                }
            }
        }
    }


    /**
     * 查询预约历史
     * @param req
     * @return
     */
    public PageData<ListBookRsp> userOrderHistory(ListBookReq req) {

        com.github.pagehelper.Page<ListBookRsp> page = PageHelper.startPage(
                req.getCurrentPage(), req.getPageSize()
        );
        List<ListBookRsp> result = bookService.ListBookRsp(req);
        int longs = ((Number) page.getTotal()).intValue();
        PageData<ListBookRsp> pageData = PageData.of(result,page.getPageNum(),page.getPageSize(),longs);
        return pageData;
    }

    /**
     * 查询药品列表
     * @param req
     * @return
     */
    public PageData<MedicalRsp> medicalList(MedicalListReq req) {
        com.github.pagehelper.Page<DepartmentRsp> page = PageHelper.startPage(
                req.getCurrentPage(), req.getPageSize()
        );
        List<MedicalRsp> list = hospitalMedicalService.selectByList(req);
        int longs = ((Number) page.getTotal()).intValue();
        PageData<MedicalRsp> pageData = PageData.of(list,page.getPageNum(),page.getPageSize(),longs);
        return pageData;
    }
}
